"""设备事件和操作日志管理

职责划分:
- 设备事件(DeviceEvent): 记录设备生命周期中的重大事件,如替换、报废、故障、恢复等
- 设备操作日志(DeviceOperationLog): 记录设备的日常CRUD操作,如创建、更新、删除等
- 审计日志(AuditLog): 系统级操作审计,由框架自动记录所有API调用
"""
from datetime import datetime
from typing import Optional

from fastapi import APIRouter, Depends, Path, Query

from app.common.auth import check_permission
from app.common.common import DbDep, AuditLogDep
from app.crud.device_event_crud import (
	get_device_event_by_id, get_device_event_list,
	get_device_operation_log_by_id, get_device_operation_log_list,
	get_device_events_by_device, get_device_operation_logs_by_device,
	get_meter_rtu_history_events
)
from app.models.device_models import DeviceEvent, DeviceOperationLog
from app.schemas.device_schemas import DeviceEventQuery, DeviceOperationLogQuery
from app.schemas.user_schemas import UserInDB
from common.exceptions import BizException, ErrorCode
from common.response import ApiResponse, PaginatedResponse

router = APIRouter(prefix="/device-events", tags=["设备事件和操作日志"])

# 权限依赖
require_event_view = check_permission("device:event:view")

require_log_view = check_permission("device:log:view")

# 事件写权限
require_event_manage = check_permission("device:event:manage")


# ========================== 设备事件 ==========================


@router.get(
	"/events/{event_id}",
	response_model=ApiResponse[DeviceEvent],
	summary="获取设备事件详情"
)
async def get_device_event(
		db: DbDep,
		_audit: AuditLogDep,
		event_id: int = Path(..., description="设备事件ID"),
		_: UserInDB = Depends(require_event_view),
) -> ApiResponse[DeviceEvent]:
	"""根据ID获取设备事件详情"""
	event = await get_device_event_by_id(db, event_id)
	if not event:
		raise BizException.from_error_code(
			ErrorCode.NOT_FOUND, message="设备事件不存在"
		)
	return ApiResponse.success(event)


@router.get(
	"/events",
	response_model=ApiResponse[PaginatedResponse[DeviceEvent]],
	summary="分页获取设备事件列表"
)
async def list_device_events(
		db: DbDep,
		_audit: AuditLogDep,
		page: int = Query(1, ge=1, description="页码"),
		size: int = Query(20, ge=1, le=100, description="每页大小"),
		keyword: Optional[str] = Query(None, description="关键字搜索"),
		device_id: Optional[int] = Query(None, description="设备ID"),
		device_type: Optional[str] = Query(None, description="设备类型(STATION/BOX/RTU/METER)"),
		event_type: Optional[str] = Query(None, description="事件类型"),
		start_time: Optional[datetime] = Query(None, description="开始时间"),
		end_time: Optional[datetime] = Query(None, description="结束时间"),
		_: UserInDB = Depends(require_event_view),
) -> ApiResponse[PaginatedResponse[DeviceEvent]]:
	"""分页获取设备事件列表,支持按设备ID、类型、事件类型筛选"""
	query = DeviceEventQuery(
		page=page,
		size=size,
		keyword=keyword,
		device_id=device_id,
		device_type=device_type,
		event_type=event_type,
		start_time=start_time,
		end_time=end_time
	)
	total, events = await get_device_event_list(db, query)

	return ApiResponse.success(
		PaginatedResponse[DeviceEvent](
			total=total,
			items=events,
			page=page,
			size=size,
			pages=(total + size - 1) // size,
			has_next=page * size < total,
			has_prev=page > 1
		)
	)


@router.get(
	"/devices/{device_type}/{device_id}/events",
	response_model=ApiResponse[PaginatedResponse[DeviceEvent]],
	summary="查询某个设备的事件列表"
)
async def get_device_events(
		db: DbDep,
		_audit: AuditLogDep,
		device_type: str = Path(..., description="设备类型(STATION/BOX/RTU/METER)"),
		device_id: int = Path(..., description="设备ID"),
		page: int = Query(1, ge=1, description="页码"),
		size: int = Query(20, ge=1, le=100, description="每页大小"),
		_: UserInDB = Depends(require_event_view),
) -> ApiResponse[PaginatedResponse[DeviceEvent]]:
	"""查询某个设备的事件历史"""
	total, events = await get_device_events_by_device(db, device_id, device_type, page, size)

	return ApiResponse.success(
		PaginatedResponse[DeviceEvent](
			total=total,
			items=events,
			page=page,
			size=size,
			pages=(total + size - 1) // size,
			has_next=page * size < total,
			has_prev=page > 1
		)
	)


# ========================== 设备事件查询 ==========================

@router.get(
	"/meters/{meter_serial_no}/rtu-history",
	response_model=ApiResponse[PaginatedResponse[DeviceEvent]],
	summary="查询电表的RTU历史事件"
)
async def get_meter_rtu_history(
		db: DbDep,
		_audit: AuditLogDep,
		meter_serial_no: str = Path(..., description="电表序列号"),
		page: int = Query(1, ge=1, description="页码"),
		size: int = Query(20, ge=1, le=100, description="每页大小"),
		_: UserInDB = Depends(require_event_view),
) -> ApiResponse[PaginatedResponse[DeviceEvent]]:
	"""查询某电表的RTU历史事件(绑定/解绑/替换等)"""
	# 调用CRUD层查询
	total, events = await get_meter_rtu_history_events(db, meter_serial_no, page, size)
	
	return ApiResponse.success(
		PaginatedResponse[DeviceEvent](
			total=total,
			items=events,
			page=page,
			size=size,
			pages=(total + size - 1) // size,
			has_next=page * size < total,
			has_prev=page > 1
		)
	)


# ========================== 操作日志 ==========================


@router.get(
	"/logs/{log_id}",
	response_model=ApiResponse[DeviceOperationLog],
	summary="获取设备操作日志详情"
)
async def get_device_operation_log(
		db: DbDep,
		_audit: AuditLogDep,
		log_id: int = Path(..., description="设备操作日志ID"),
		_: UserInDB = Depends(require_log_view),
) -> ApiResponse[DeviceOperationLog]:
	"""根据ID获取设备操作日志详情"""
	log = await get_device_operation_log_by_id(db, log_id)
	if not log:
		raise BizException.from_error_code(
			ErrorCode.NOT_FOUND, message="设备操作日志不存在"
		)
	return ApiResponse.success(log)


@router.get(
	"/logs",
	response_model=ApiResponse[PaginatedResponse[DeviceOperationLog]],
	summary="分页获取设备操作日志列表"
)
async def list_device_operation_logs(
		db: DbDep,
		_audit: AuditLogDep,
		page: int = Query(1, ge=1, description="页码"),
		size: int = Query(20, ge=1, le=100, description="每页大小"),
		keyword: Optional[str] = Query(None, description="关键字搜索"),
		device_id: Optional[int] = Query(None, description="设备ID"),
		device_type: Optional[str] = Query(None, description="设备类型(STATION/BOX/RTU/METER)"),
		op_type: Optional[str] = Query(None, description="操作类型"),
		start_time: Optional[datetime] = Query(None, description="开始时间"),
		end_time: Optional[datetime] = Query(None, description="结束时间"),
		_: UserInDB = Depends(require_log_view),
) -> ApiResponse[PaginatedResponse[DeviceOperationLog]]:
	"""分页获取设备操作日志列表,支持按设备ID、类型、操作类型筛选"""
	query = DeviceOperationLogQuery(
		page=page,
		size=size,
		keyword=keyword,
		device_id=device_id,
		device_type=device_type,
		op_type=op_type,
		start_time=start_time,
		end_time=end_time
	)
	total, logs = await get_device_operation_log_list(db, query)

	return ApiResponse.success(
		PaginatedResponse[DeviceOperationLog](
			total=total,
			items=logs,
			page=page,
			size=size,
			pages=(total + size - 1) // size,
			has_next=page * size < total,
			has_prev=page > 1
		)
	)


@router.get(
	"/devices/{device_type}/{device_id}/logs",
	response_model=ApiResponse[PaginatedResponse[DeviceOperationLog]],
	summary="查询某个设备的操作日志"
)
async def get_device_logs(
		db: DbDep,
		_audit: AuditLogDep,
		device_type: str = Path(..., description="设备类型(STATION/BOX/RTU/METER)"),
		device_id: int = Path(..., description="设备ID"),
		page: int = Query(1, ge=1, description="页码"),
		size: int = Query(20, ge=1, le=100, description="每页大小"),
		_: UserInDB = Depends(require_log_view),
) -> ApiResponse[PaginatedResponse[DeviceOperationLog]]:
	"""查询某个设备的操作历史"""
	total, logs = await get_device_operation_logs_by_device(db, device_id, device_type, page, size)

	return ApiResponse.success(
		PaginatedResponse[DeviceOperationLog](
			total=total,
			items=logs,
			page=page,
			size=size,
			pages=(total + size - 1) // size,
			has_next=page * size < total,
			has_prev=page > 1
		)
	)
